#pragma once

#include <sys/select.h>
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include "Sock.hpp"

static uint16_t default_port = 8080;

const static int default_fds = -1;

typedef int type_t;

class SelectServer
{
    const static int N = (sizeof(fd_set) * 8);

public:
    SelectServer(uint16_t serverPort = default_port)
        : _serverPort(serverPort)
    {
    }

    void Init()
    {
        _sock.Socket();
        _sock.Bind(_serverPort);
        _sock.Listen();

        for (int i = 0; i < N; ++i)
        {
            _RfdsArray[i] = default_fds;
        }
    }

    void Accept()
    {
        std::string clientIp;
        uint16_t clientPort;
        int sock = _sock.Accept(&clientIp, &clientPort);
        if (sock < 0)
            return;
        LogMessage(Debug, "%s-%d accept success", clientIp.c_str(), clientPort);
        int pos = 0;
        for (pos = 0; pos < N; ++pos)
        {
            if (_RfdsArray[pos] == default_fds)
                break;
        }
        if (pos >= N)
        {
            LogMessage(Warning, "rfds已经满了");
            close(sock);
        }
        else
        {
            _RfdsArray[pos] = sock;
        }
    }

    void Recv(int sock, int i)
    {
        char buffer[1024];
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        socklen_t len = sizeof(local);
        int n = recvfrom(sock, &buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&local, &len);
        if (n == 0)
        {
            std::cout << "client exit" << std::endl;
            close(sock);
            _RfdsArray[i] = default_fds;
        }
        else if (n < 0)
        {
            LogMessage(Warning, "read occur error , sock : %d , %d %s", sock, errno, strerror(errno));
            close(sock);
            _RfdsArray[i] = default_fds;
        }
        else
        {
            buffer[n] = '\0';
            std::cout << "client send # " << buffer << std::endl;
            std::string message = "[server send] # ";
            message += buffer;
            send(sock, message.c_str(), message.size(), 0);
        }
    }

    void HandlerEvent(fd_set &set)
    {
        for (int i = 0; i < N; ++i)
        {
            if (_RfdsArray[i] == default_fds)
                continue;

            if (_RfdsArray[i] == _sock.Fd() && FD_ISSET(_RfdsArray[i], &set))
                Accept();
            else if (_RfdsArray[i] != _sock.Fd() && FD_ISSET(_RfdsArray[i], &set))
                Recv(_RfdsArray[i], i);
        }
    }

    void Start()
    {
        _RfdsArray[0] = _sock.Fd();
        while (true)
        {
            fd_set set;
            FD_ZERO(&set);
            int maxfd = _RfdsArray[0];

            for (int i = 0; i < N; ++i)
            {
                if (_RfdsArray[i] == default_fds)
                    continue;

                FD_SET(_RfdsArray[i], &set); // 设置
                if (maxfd < _RfdsArray[i])   // 寻找最大fd的数字
                    maxfd = _RfdsArray[i];
            }
            struct timeval timeout = {1, 0};
            int n = select(maxfd + 1, &set, nullptr, nullptr, &timeout);
            if (n == 0)
                LogMessage(Debug, "timeout , %s %d", errno, strerror(errno));
            else if (n < 0)
                LogMessage(errno, "%d %s", errno, strerror(errno));
            else
            {
                std::cout << "有一个就绪事件发生了 " << n << std::endl;
                Print();
                HandlerEvent(set);
            }
        }
    }

    void Print()
    {
        for (int i = 0; i < N; ++i)
        {
            if(_RfdsArray[i] != default_fds)
                std::cout << _RfdsArray[i] << " ";
        }
        std::cout << std::endl;
    }

    ~SelectServer()
    {
    }

private:
    uint16_t _serverPort;
    Sock _sock;
    type_t _RfdsArray[N];
};